/*
 * Copyright 2016 The Cartographer Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SLAM_ROS_SLAM_ROS_SENSOR_BRIDGE_H
#define SLAM_ROS_SLAM_ROS_SENSOR_BRIDGE_H

#include <memory>

#include "absl/types/optional.h"
#include "geometry_msgs/msg/transform.hpp"
#include "geometry_msgs/msg/transform_stamped.hpp"
#include "nav_msgs/msg/occupancy_grid.hpp"
#include "agv_msgs/msg/odometry_lite.hpp"
#include "sensor_msgs/msg/imu.hpp"
#include "sensor_msgs/msg/laser_scan.hpp"
#include "sensor_msgs/msg/multi_echo_laser_scan.hpp"
#include "sensor_msgs/msg/nav_sat_fix.hpp"
#include "sensor_msgs/msg/point_cloud2.hpp"
#include "slam/mapping/trajectory_builder_interface.h"
#include "slam/sensor/fixed_frame_pose_data.h"
#include "slam/sensor/imu_data.h"
#include "slam/sensor/odometry_data.h"
#include "slam/transform/rigid_transform.h"
#include "slam/transform/transform.h"
#include "slam_ros/tf_bridge.h"
#include "slam_ros_msgs/msg/landmark_list.hpp"
#include "slam_ros_msgs/msg/qr_code.hpp"
#include "tf2_ros/buffer.h"

namespace slam_ros {

class SensorBridge {
 public:
  explicit SensorBridge(
      int num_subdivisions_per_laser_scan, 
      const std::string& tracking_frame,
      double lookup_transform_timeout_sec, 
      tf2_ros::Buffer* tf_buffer,
      ::slam::mapping::TrajectoryBuilderInterface* trajectory_builder);

  SensorBridge(const SensorBridge&) = delete;
  SensorBridge& operator=(const SensorBridge&) = delete;

  std::unique_ptr<::slam::sensor::OdometryData> ToOdometryData(
      const agv_msgs::msg::OdometryLite::ConstSharedPtr& msg);
  void HandleOdometryMessage(
      const std::string& sensor_id,
      const agv_msgs::msg::OdometryLite::ConstSharedPtr& msg);
  void HandleNavSatFixMessage(
      const std::string& sensor_id,
      const sensor_msgs::msg::NavSatFix::ConstSharedPtr& msg);
  void HandleLandmarkMessage(
      const std::string& sensor_id,
      const slam_ros_msgs::msg::LandmarkList::ConstSharedPtr& msg);

  void HandleQRCodeMessage(
      const std::string& sensor_id,
      const slam_ros_msgs::msg::QRCode& msg,
      const double translation_weight,
      const double rotation_weight);

  std::unique_ptr<::slam::sensor::ImuData> ToImuData(
      const sensor_msgs::msg::Imu::ConstSharedPtr& msg);
  void HandleImuMessage(
      const std::string& sensor_id,
      const sensor_msgs::msg::Imu::ConstSharedPtr& msg);
  void HandleLaserScanMessage(
      const std::string& sensor_id,
      const sensor_msgs::msg::LaserScan::ConstSharedPtr& msg);
  void HandleMultiEchoLaserScanMessage(
      const std::string& sensor_id,
      const sensor_msgs::msg::MultiEchoLaserScan::ConstSharedPtr& msg);
  void HandlePointCloud2Message(
      const std::string& sensor_id,
      const sensor_msgs::msg::PointCloud2::ConstSharedPtr& msg);

  const TfBridge& tf_bridge() const;

 private:
  void HandleLaserScan(
      const std::string& sensor_id, 
      ::slam::common::Time start_time,
      const std::string& frame_id,
      const ::slam::sensor::PointCloudWithIntensities& points);
  void HandleRangefinder(
      const std::string& sensor_id,
      ::slam::common::Time time,
      const std::string& frame_id,
      const ::slam::sensor::TimedPointCloud& ranges);

  const int num_subdivisions_per_laser_scan_;
  std::map<std::string, slam::common::Time>
      sensor_to_previous_subdivision_time_;
  const TfBridge tf_bridge_;
  ::slam::mapping::TrajectoryBuilderInterface* const trajectory_builder_;

  absl::optional<::slam::transform::Rigid3d> ecef_to_local_frame_;
};

}  // namespace slam_ros

#endif  // SLAM_ROS_SLAM_ROS_SENSOR_BRIDGE_H